package com.xzcs.shiro;

import com.xzcs.util.common.SerializeUtils;
import com.xzcs.util.redis.JedisUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.SerializationUtils;

import java.io.Serializable;

/**
 * @desc: 
 * @author: chang
 * @date: 2017/5/23
 */
public class MyRedisSessionDao extends EnterpriseCacheSessionDAO {
    public Logger logger = LoggerFactory.getLogger(getClass());

    private JedisUtils jedisUtils;

    private int sessionTimeOut = 1800;
    private String keyPrefix = "shiro_session:";

    public JedisUtils getJedisUtils() {
        return jedisUtils;
    }

    public void setJedisUtils(JedisUtils jedisUtils) {
        this.jedisUtils = jedisUtils;
    }

    public long getSessionTimeOut() {
        return sessionTimeOut;
    }

    public void setSessionTimeOut(int sessionTimeOut) {
        this.sessionTimeOut = sessionTimeOut;
    }

    private byte[] getByteKey(Object key){
        if(key instanceof String){
            String preKey = this.keyPrefix + (String)key;
            return preKey.getBytes();
        }else{
            return SerializeUtils.serialize(key);
        }
    }

    private void saveSession(Serializable sessionId, Session session) throws UnknownSessionException {
        if(session == null || session.getId() == null){
            logger.error("session or session id is null");
            return;
        }
        byte[] key = getByteKey(sessionId);
        byte[] value = SerializationUtils.serialize(session);
        session.setTimeout(sessionTimeOut * 1000);
        jedisUtils.setex(key, sessionTimeOut, value);
    }

    @Override
    protected Serializable doCreate(Session session) {
        Serializable sessionId = super.doCreate(session);
        this.saveSession(sessionId, session);
        return sessionId;
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {
        // 先从缓存中获取session，如果没有再去数据库中获取
        Session session = super.doReadSession(sessionId);
        if(session == null){
            byte[] bytes = jedisUtils.get(getByteKey(sessionId));
            if(bytes != null && bytes.length > 0){
                session = (Session)SerializationUtils.deserialize(bytes);
            }
        }
        return session;
    }

    @Override
    protected void doUpdate(Session session) {
        super.doUpdate(session);
        this.saveSession(session.getId(), session);
    }

    @Override
    protected void doDelete(Session session) {
        super.doDelete(session);
        if(session == null || session.getId() == null){
            logger.error("session or session id is null");
            return;
        }
        jedisUtils.del(getByteKey(session.getId()));
    }
}
